home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / writeTree.c < prev   
C/C++ Source or Header  |  1990-08-16  |  19KB  |  710 lines

  1. /*
  2.  * @(#)writeTree.c    1.6  3/13/89
  3.  */
  4. #include "assert.h"
  5. #include "error.h"
  6. #include "scan.h"
  7. #include "nodes.h"
  8. #include "symbols.h"
  9. #include "MyParser.h"
  10. #include "semantics.h"
  11. #include "system.h"
  12. #include "map.h"
  13. #include "version.h"
  14. #include "environment.h"
  15. #include "flags.h"
  16. #include <a.out.h>
  17. #include "builtins.h"
  18. #include "trace.h"
  19.  
  20. extern char *ATName();
  21. extern void myLink();
  22.  
  23. #define MAXRELOCATIONBLOCKS 400
  24. #define BLOCKSIZE 1024
  25. #define RELOCATIONSPERBLOCK (1024 / sizeof(struct relocation_info))
  26. static char *theOIDFileName;
  27. static int treeVersion = TREEVERSION;
  28.  
  29. static struct exec header;
  30. static struct sts {
  31.   int size;
  32.   char strings[20];
  33. } *stringTable;
  34. static int stringTableSize;
  35. static struct nlist symbolTable;
  36. typedef struct {
  37.   struct relocation_info rl[RELOCATIONSPERBLOCK];
  38. } RelocationBlock, *RelocationBlockPtr;
  39. static RelocationBlockPtr relocationBlocks[MAXRELOCATIONBLOCKS];
  40. static int nextRelocationBlockIndex;
  41. static RelocationBlockPtr rbp;
  42. static struct relocation_info *rp, *rpe;
  43. static int nextOffset;
  44. static FILE *fp;
  45. static Map offsetMap, CTMap;
  46.  
  47. static int Pass;
  48.  
  49. static void _DoAReference(), writeInt(), Pass1(), Pass2(), writeBody();
  50. #define OFFSETOF(fNode) Map_Lookup(offsetMap, (int) fNode)
  51. #define SETOFFSET(fNode, value) Map_Insert(offsetMap, (int)fNode, (int)value)
  52. static int getOffset();
  53.  
  54. static NodePtr theRoot, aGlobalRef;
  55.  
  56. /*
  57.  * When we write out the file, we write out all the tree nodes.  Global
  58.  * references are changed to remove the "cache".  Builtin object references
  59.  * are left alone.  We then write out the modified symbol table and ident
  60.  * table entries.
  61.  */
  62.  
  63. static void squirrelSymbol(p)
  64. NodePtr p;
  65. {
  66.   register Symbol st = p->b.symdef.symbol;
  67.   int filePosition, rightFilePosition;
  68.   int thisSymbolOffset;
  69.  
  70.   st = ST_Fetch(st);
  71.   if (OFFSETOF(st) == NIL) {
  72.     assert(Pass == 1);
  73.     thisSymbolOffset = nextOffset;
  74.     SETOFFSET(st, thisSymbolOffset);
  75.     nextOffset += 2 + 2 + 1 + 1 + 1 + 1;    /* up to value */
  76.     if ((int)st->value.ATinfo > 0x200) _DoAReference(nextOffset);
  77.     nextOffset += sizeof(NodePtr);
  78.     if ((int)st->value.CTinfo > 0x200) _DoAReference(nextOffset);
  79.     nextOffset += sizeof(NodePtr);
  80.     if ((int)st->value.value  > 0x200) _DoAReference(nextOffset);
  81.     nextOffset += sizeof(NodePtr);
  82.     nextOffset += sizeof(Address);
  83.     if (st->itsName != NULL) _DoAReference(nextOffset);
  84.     nextOffset += sizeof(char *);
  85.     if (st->itsName != NULL) nextOffset += ((strlen(st->itsName)+1+3) & ~0x3);
  86.     Pass1(st->value.ATinfo, FALSE);
  87.     if ((int) st->value.CTinfo > 0x200) Map_Insert(CTMap, (int)st->value.CTinfo, 1);
  88.     Pass1(st->value.value, FALSE);
  89.   }
  90.   if (Pass == 2) {
  91.     /* write the tree node */
  92.     filePosition = ftell(fp);
  93.     rightFilePosition = getOffset(p) + sizeof(struct exec);
  94.     assert (filePosition == rightFilePosition);
  95.     writeBody(p, 1);
  96.     writeInt(getOffset((NodePtr)p->b.symdef.symbol));
  97.     /* now check for the symbol itself */
  98.     thisSymbolOffset = OFFSETOF(st);
  99.     if (thisSymbolOffset < 0) return;
  100.     SETOFFSET(st, -thisSymbolOffset);
  101.     filePosition = ftell(fp);
  102.     rightFilePosition = thisSymbolOffset + sizeof(struct exec);
  103.     assert (filePosition == rightFilePosition);
  104.     if (fwrite((char *)st, 8, 1, fp) != 1) assert(FALSE);
  105.     writeInt(getOffset(st->value.ATinfo));
  106.     writeInt(getOffset(st->value.CTinfo));
  107.     writeInt(getOffset(st->value.value ));
  108.     if (fwrite((char *)&st->v.address, sizeof(Address), 1, fp) != 1) assert(FALSE);
  109.     writeInt(thisSymbolOffset + sizeof(STEntry));
  110.     filePosition = ftell(fp);
  111.     rightFilePosition += sizeof(STEntry);
  112.     assert(filePosition == rightFilePosition);
  113.     if (st->itsName != NULL) {
  114.       register int i, strLength;
  115.       i = strlen(st->itsName);
  116.       strLength = (i+1+3) & ~0x3;
  117.       if (fwrite(st->itsName, 1, i, fp) != i) assert(FALSE);
  118.       for (; i < strLength; i++) (void) fputc('\0', fp);
  119.     }
  120.     Pass2(st->value.ATinfo, FALSE);
  121.     Pass2(st->value.value, FALSE);
  122.   }
  123. }
  124.  
  125. /*
  126. * This one needs to initialize the header, and initialize the mapping
  127. * structures.
  128. */
  129.  
  130. static void initializeOutput(treeName)
  131. char *treeName;
  132. {
  133. #ifdef sun
  134.   header.a_dynamic = 0;
  135.   header.a_machtype = M_68020;
  136. #endif
  137.   header.a_magic = 0407;
  138.   header.a_text = 0;
  139.   header.a_bss = 0;
  140.   header.a_syms = 1 * sizeof(struct nlist);
  141.   symbolTable.n_un.n_strx = 4;
  142.   symbolTable.n_type = N_DATA;
  143.   if (*treeName == '_') symbolTable.n_type |= N_EXT;
  144.   symbolTable.n_other = 0;
  145.   symbolTable.n_desc = 0;
  146.   symbolTable.n_value = 12;
  147.   stringTableSize = (strlen(treeName) + 1 + 3) & ~0x3;
  148.   stringTableSize += 4;
  149.   stringTable = (struct sts *) calloc((unsigned)stringTableSize, 1);
  150.   stringTable->size = stringTableSize;
  151.   (void) strcpy(stringTable->strings, treeName);
  152.   header.a_entry = 0;
  153.   header.a_trsize = 0;
  154.   nextRelocationBlockIndex = 0;
  155.   rbp = (RelocationBlockPtr) calloc(sizeof (RelocationBlock), 1);
  156.   relocationBlocks[nextRelocationBlockIndex++] = rbp;
  157.   rp = &rbp->rl[0];
  158.   rpe = &rp[RELOCATIONSPERBLOCK];
  159.   nextOffset = 12;
  160.   /*
  161.    * Leaves header.a_data and header.a_drsize undone.
  162.    */
  163.   offsetMap = Map_Create();
  164.   CTMap = Map_Create();
  165.   Pass = 1;
  166. }
  167.  
  168. static void Pass1CTs()
  169. {
  170.   NodePtr ct;
  171.   int value;
  172.   Map_For(CTMap, ct, value)
  173.     assert(value == 1);
  174.     if (ct->tag == P_OBLIT && ct->b.oblit.f.dependsOnTypeVariable) {
  175.       /* do nothing */
  176.     } else {
  177.       if (OFFSETOF(ct) == NIL) {
  178.     /* we have not done this one already */
  179.     Pass1(ct, TRUE);
  180.       }
  181.     }
  182.   Map_Next
  183. }
  184.  
  185. static void Pass2CTs()
  186. {
  187.   NodePtr ct;
  188.   int value;
  189.   Map_For(CTMap, ct, value)
  190.     assert(value == 1);
  191.     if (ct->tag == P_OBLIT && ct->b.oblit.f.dependsOnTypeVariable) {
  192.       /* do nothing */
  193.     } else {
  194.       if (OFFSETOF(ct) >= 0) {
  195.     /* we have not done this one already */
  196.     Pass2(ct, TRUE);
  197.       }
  198.     }
  199.   Map_Next
  200. }
  201.  
  202. static void intermediate()
  203. {
  204.   int i;
  205.   header.a_data = nextOffset;
  206.   header.a_drsize = (nextRelocationBlockIndex - 1) * BLOCKSIZE +
  207.     (int) rp - (int) rbp;
  208.   if (fwrite((char *)&header, sizeof(header), 1, fp) != 1) assert(FALSE);
  209.   /* We write the tree Version number here.  We also need to make
  210.      the offsets all non zero. */
  211.   i = TREEMAGIC;
  212.   if (fwrite((char *)&i, sizeof(int), 1, fp) != 1) assert(FALSE);
  213.   if (fwrite((char *)&treeVersion, sizeof(int), 1, fp) != 1) assert(FALSE);
  214.   if (fwrite((char *)&nextOffset, sizeof(int), 1, fp) != 1) assert(FALSE);
  215.   Pass = 2;
  216. }
  217.  
  218. static void finalize()
  219. {
  220.   int filePosition, rightFilePosition;
  221.   register int i;
  222.   filePosition = ftell(fp);
  223.   rightFilePosition = sizeof(struct exec) + header.a_data;
  224.   assert (filePosition == rightFilePosition);
  225.   for (i = 0; i < nextRelocationBlockIndex - 1; i++) {
  226.     if (fwrite((char *)relocationBlocks[i], BLOCKSIZE, 1, fp) != 1) assert(FALSE);
  227.     free((char *)relocationBlocks[i]);
  228.   }
  229.   i = (int) rp - (int) &rbp->rl[0];
  230.   if (i != 0) if (fwrite((char *)rbp, i, 1, fp) != 1) assert(FALSE);
  231.   free((char *)rbp);
  232.   if (fwrite((char *)&symbolTable, sizeof(symbolTable), 1, fp) != 1) assert(FALSE);
  233.   if (fwrite((char *)stringTable, stringTableSize, 1, fp) != 1) assert(FALSE);
  234.   free((char *)stringTable);
  235.   Map_Destroy(offsetMap);
  236.   Map_Destroy(CTMap);
  237. }
  238.  
  239. #define DOAREFERENCE(fNode, fE) \
  240.   if ((int) (fE) > 0x200) \
  241.     _DoAReference(thisNodeOffset + (int)(&(fE))-(int)fNode)
  242.  
  243. static void _DoAReference(offset)
  244. int offset;
  245. {
  246.   register struct relocation_info *myrp;
  247.   if (rp >= rpe) {
  248.     if (nextRelocationBlockIndex >= MAXRELOCATIONBLOCKS) {
  249.       fprintf(stderr, "Out of relocation blocks (allocated %d)\n",
  250.     MAXRELOCATIONBLOCKS * RELOCATIONSPERBLOCK);
  251.       exit(1);
  252.     }
  253.     rbp = (RelocationBlockPtr) calloc(sizeof (RelocationBlock), 1);
  254.     relocationBlocks[nextRelocationBlockIndex++] = rbp;
  255.     rp = &rbp->rl[0];
  256.     rpe = &rp[RELOCATIONSPERBLOCK];
  257.   }
  258.   myrp = rp++;
  259.   myrp->r_address = offset;
  260.   myrp->r_symbolnum = N_DATA;
  261.   myrp->r_pcrel = 0;
  262.   myrp->r_length = 2;
  263.   myrp->r_extern = 0;
  264. }
  265.  
  266. static Boolean doneFirstNode;
  267.  
  268. static Boolean OBLitShouldBeSeparate(p)
  269. NodePtr p;
  270. {
  271.   if (p != theRoot && p->b.oblit.f.writeSeparately) return(TRUE);
  272.   if (!bflag && p->tag == P_OBLIT && p->b.oblit.f.inExecutableConstruct &&
  273.       (EnvironmentStage)Map_Lookup(environmentMap, (int)p->b.oblit.codeOID) == E_Imported)
  274.     return(TRUE);
  275.   return(FALSE);
  276. }
  277.  
  278. static void scheduleOBLitOutput(p, id)
  279. NodePtr p;
  280. OID id;
  281. {
  282.   if (bflag) {
  283.     if (((id & 0xff000000) == (OID) 0xff000000) &&
  284.         ((id & 0x1f) == (theRoot->b.oblit.id & 0x1f))) {
  285.       scheduleOutput(id);
  286.     } else if ((id & 0xffffff00) != (OID)0xff000000) {
  287.       TRACE2(builtins, 1, "Writing tree for non-builtin %s with id 0x%08x", ATName(p), id);
  288.       scheduleOutput(id);
  289.     } else {
  290.       TRACE2(builtins, 1, "Not writing tree for %s with id 0x%08x", ATName(p), id);
  291.     }
  292.   } else {
  293.     scheduleOutput(id);
  294.   }
  295. }
  296.  
  297. static void Pass1(fNode, isCT)
  298. register NodePtr fNode;
  299. Boolean isCT;
  300. {
  301.   register int i;
  302.   int thisNodeOffset;
  303.   Boolean done = FALSE;
  304.   Symbol st;
  305.   NodePtr saveAT;
  306.  
  307.   if ((int)fNode <= 0x200) {
  308.     /* don't worry about these. */
  309.   } else if (fNode == theRoot && doneFirstNode) {
  310.     nextOffset += UsedNodeSize(aGlobalRef);
  311.   } else if (OFFSETOF(fNode) != NIL) {
  312.     /* We've done this one already */
  313.   } else {
  314.     doneFirstNode = TRUE;
  315.     thisNodeOffset = nextOffset;
  316.     SETOFFSET(fNode, thisNodeOffset);
  317.     nextOffset += UsedNodeSize(fNode);
  318.     switch (fNode->tag) {
  319.       case P_GLOBALREF:
  320.     done = TRUE;
  321.     break;
  322.       case P_OPNAME:
  323.     done = TRUE;
  324.     break;
  325.       case P_ATLIT:
  326.     assert(!isCT);
  327.     if (OBLitShouldBeSeparate(fNode)) {
  328.       /*
  329.        * We have a pointer to a manifest atlit.  We need to write out a
  330.        * globalref node.
  331.        */
  332.       nextOffset -= UsedNodeSize(fNode);
  333.       nextOffset += UsedNodeSize(aGlobalRef);
  334.       done = TRUE;
  335.     }
  336.     break;
  337.       case P_OBLIT:
  338.     if (isCT || OBLitShouldBeSeparate(fNode)) {
  339.       /*
  340.        * We have a pointer to a manifest oblit.  We need to write out a
  341.        * globalref node.
  342.        */
  343.       nextOffset -= UsedNodeSize(fNode);
  344.       nextOffset += UsedNodeSize(aGlobalRef);
  345.       done = TRUE;
  346.     } else {
  347.       if (fNode->b.oblit.f.isTypeVariable) {
  348.         saveAT = fNode->b.oblit.myat;
  349.         fNode->b.oblit.myat = NULL;
  350.       }
  351.       st = ST_Fetch(fNode->b.oblit.name->b.symdef.symbol);
  352.       st->value.ATinfo = fNode->b.oblit.myat;
  353.       for (i = fNode->firstChild; i < fNode->nChildren; i++) {
  354.         DOAREFERENCE(fNode, fNode->b.children[i]);
  355.         Pass1(fNode->b.children[i], FALSE);
  356.       }
  357.       if (fNode->b.oblit.f.isTypeVariable) {
  358.         fNode->b.oblit.myat = saveAT;
  359.         st = ST_Fetch(fNode->b.oblit.name->b.symdef.symbol);
  360.         st->value.ATinfo = saveAT;
  361.       }
  362.       done = TRUE;
  363.     }
  364.     break;
  365.       case T_IDENT:
  366.     done = TRUE;
  367.     break;
  368.       case T_STRING:
  369.       case P_CHARLIT:
  370.       case P_INTLIT:
  371.       case P_REALLIT:
  372.       case P_STRINGLIT:
  373.     /* We write the string */
  374.     DOAREFERENCE(fNode, fNode->b.string.string);
  375.     nextOffset += ((strlen(fNode->b.string.string)+1+3) & ~0x3);
  376.     done = TRUE;
  377.     break;
  378.       case P_BOOLLIT:
  379.     done = TRUE;
  380.     break;
  381.       case P_BUILTINLIT:
  382.     done = TRUE;
  383.     break;
  384.       case P_PARAM:
  385.       case P_ARG:
  386.     break;
  387.       case P_SYMREF:
  388.       case P_SYMDEF:
  389.     DOAREFERENCE(fNode, fNode->b.symdef.symbol);
  390.     squirrelSymbol(fNode);
  391.     done = TRUE;
  392.     break;
  393.       case P_FIELDREF:
  394.     assert(FALSE);
  395.     break;
  396.       case P_OPSIG:
  397.     break;
  398.       case P_COMP:
  399.       case P_IMPORT:
  400.     assert(FALSE);
  401.     break;
  402.       case P_EXPORT:
  403.     break;
  404.       case P_RECORDLIT:
  405.       case P_UNIONLIT:
  406.       case P_ENUMLIT:
  407.     assert(FALSE);
  408.     break;
  409.       case P_CONSTDECL:
  410.       case P_VARDECL:
  411.       case P_VECTORLIT:
  412.       case P_PRAGMA:
  413.       case P_MONITOR:
  414.       case P_OPDEF:
  415.       case P_PROCESSDEF:
  416.       case P_INITDEF:
  417.       case P_RECOVERYDEF:
  418.       case P_BLOCK:
  419.       case P_UNAVAILABLEHANDLER:
  420.       case P_FAILUREHANDLER:
  421.       case P_IFSTAT:
  422.       case P_IFCLAUSE:
  423.       case P_ELSECLAUSE:
  424.       case P_LOOPSTAT:
  425.       case P_EXITSTAT:
  426.       case P_ASSIGNSTAT:
  427.       case P_ASSERTSTAT:
  428.       case P_FIXSTAT:
  429.       case P_REFIXSTAT:
  430.       case P_UNFIXSTAT:
  431.       case P_MOVESTAT:
  432.       case P_VIEW:
  433.       case P_EXP:
  434.       case P_INVOC:
  435.     break;
  436.       case P_FIELDSEL:
  437.       case P_NTHRESULT:
  438.       case P_KNOWCT:
  439.       case P_KNOWLOCAL:
  440.       case P_KNOWMANIFEST:
  441.       case P_SUBSCRIPT:
  442.       case P_SELECTION:
  443.     assert(FALSE);
  444.     break;
  445.       case P_WHEREWIDGIT:
  446.       case P_PRIMSTAT:
  447.       case P_WAITSTAT:
  448.       case P_SIGNALSTAT:
  449.       case P_UNARYEXP:
  450.       case P_RESTRICT:
  451.       case P_SETQ:
  452.     break;
  453.       default:
  454.     break;
  455.     }
  456.     if (!done) for (i = fNode->firstChild; i < fNode->nChildren; i++) {
  457.       DOAREFERENCE(fNode, fNode->b.children[i]);
  458.       Pass1(fNode->b.children[i], FALSE);
  459.     }
  460.   }
  461. }
  462.  
  463. #define IABS(N) ((N) < 0 ? -(N) : (N))
  464.  
  465. static int getOffset(fNode)
  466. register NodePtr fNode;
  467. {
  468.   register int i;
  469.   if ((int) fNode <= 0x200) return ((int) fNode);
  470.   else {
  471.     i = OFFSETOF(fNode);
  472.     return (IABS(i));
  473.   }
  474. }
  475.  
  476. static void writeInt(n)
  477. int n;
  478. {
  479.   if (fwrite((char *) &n, sizeof(int), 1, fp) != 1) assert(FALSE);
  480. }
  481.  
  482. static void writeBody(fNode, n)
  483. register NodePtr fNode;
  484. int n;
  485. {
  486.   if (fwrite((char *)fNode, (2+n)*sizeof(int), 1, fp) != 1) assert(FALSE);
  487. }
  488.  
  489. static OID transOID(id)
  490. OID id;
  491. {
  492.   register OID result;
  493.   result = (OID) Map_Lookup(translateOIDMap, (int)id);
  494.   return (result == NIL ? id : result);
  495. }
  496.  
  497. static void Pass2(fNode, isCT)
  498. register NodePtr fNode;
  499. Boolean isCT;
  500. {
  501.   register int i;
  502.   Boolean done = FALSE;
  503.   int strLength;
  504.   int filePosition, rightFilePosition;
  505.  
  506.   if ((int)fNode <= 0x200) {
  507.     /* don't worry about these. */
  508.   } else if (fNode == theRoot && doneFirstNode) {
  509.     aGlobalRef->b.globalref.id = fNode->b.atlit.id;
  510.     writeBody(aGlobalRef, 2);
  511.   } else if (OFFSETOF(fNode) < 0) {
  512.     /* We've written this one already */
  513.   } else {
  514.     doneFirstNode = TRUE;
  515.     filePosition = ftell(fp);
  516.     rightFilePosition = OFFSETOF(fNode) + sizeof(struct exec);
  517.     assert (filePosition == rightFilePosition);
  518.     SETOFFSET(fNode, -OFFSETOF(fNode));
  519.     switch (fNode->tag) {
  520.       case P_GLOBALREF:
  521.     if (bflag)
  522.       fNode->b.globalref.id = transOID(fNode->b.globalref.id);
  523.     writeBody(fNode, 1);
  524.     writeInt(0);
  525.     done = TRUE;
  526.     break;
  527.       case P_OPNAME:
  528.     writeBody(fNode, 2);
  529.     done = TRUE;
  530.     break;
  531.       case P_ATLIT:
  532.     assert(!isCT);
  533.     if (OBLitShouldBeSeparate(fNode)) {
  534.       /*
  535.        * We have a pointer to a manifest atlit.  We need to write out a
  536.        * globalref node.
  537.        */
  538.       aGlobalRef->b.globalref.id = fNode->b.atlit.id;
  539.       if (bflag)
  540.         aGlobalRef->b.globalref.id = transOID(aGlobalRef->b.globalref.id);
  541.       writeBody(aGlobalRef, 2);
  542.       if (!isCT) scheduleOBLitOutput(fNode, aGlobalRef->b.globalref.id);
  543.       done = TRUE;
  544.     }
  545.     break;
  546.       case P_OBLIT:
  547.     if (isCT || OBLitShouldBeSeparate(fNode)) {
  548.       /*
  549.        * We have a pointer to a manifest oblit.  We need to write out a
  550.        * globalref node.
  551.        */
  552.       if (isCT) {
  553.         assert(fNode->b.oblit.codeOID != 0);
  554.         aGlobalRef->b.globalref.id = fNode->b.oblit.codeOID;
  555.       } else {
  556.         aGlobalRef->b.globalref.id = 
  557.           fNode->b.oblit.id ? fNode->b.oblit.id : fNode->b.oblit.codeOID;
  558.       }
  559.       if (bflag)
  560.         aGlobalRef->b.globalref.id = transOID(aGlobalRef->b.globalref.id);
  561.       writeBody(aGlobalRef, 2);
  562.       if (!isCT) scheduleOBLitOutput(fNode, aGlobalRef->b.globalref.id);
  563.       done = TRUE;
  564.     } else {
  565.       if (!bflag && fNode->b.oblit.codeOID != 0) {
  566.         char *theSecondOIDFileName;
  567.         theSecondOIDFileName = makeOIDFileName(fNode->b.oblit.codeOID);
  568.         myLink(theOIDFileName, theSecondOIDFileName, TRUE, fNode);
  569.         TRACE2(environment, 5, "Linking %s to %s", theSecondOIDFileName,
  570.           theOIDFileName);
  571.       }
  572.     }
  573.     break;
  574.       case T_IDENT:
  575.     break;
  576.       case T_STRING:
  577.       case P_CHARLIT:
  578.       case P_INTLIT:
  579.       case P_REALLIT:
  580.       case P_STRINGLIT:
  581.     /* We write the string */
  582.     writeBody(fNode, 0);
  583.     writeInt((int)(-OFFSETOF(fNode) + BODYSIZE + 4));
  584.     strLength = (strlen(fNode->b.string.string)+1+3) & ~0x3;
  585.     i = strlen(fNode->b.string.string);
  586.     if (fwrite(fNode->b.string.string, 1, i, fp) != i) assert(FALSE);
  587.     for (; i < strLength; i++) (void) fputc('\0', fp);
  588.     done = TRUE;
  589.     break;
  590.       case P_BOOLLIT:
  591.     break;
  592.       case P_BUILTINLIT:
  593.     break;
  594.       case P_PARAM:
  595.       case P_ARG:
  596.     break;
  597.       case P_SYMREF:
  598.       case P_SYMDEF:
  599.     squirrelSymbol(fNode);
  600.     done = TRUE;
  601.     break;
  602.       case P_FIELDREF:
  603.     assert(FALSE);
  604.     break;
  605.       case P_OPSIG:
  606.     break;
  607.       case P_COMP:
  608.       case P_IMPORT:
  609.     assert(FALSE);
  610.     break;
  611.       case P_EXPORT:
  612.     break;
  613.       case P_RECORDLIT:
  614.       case P_UNIONLIT:
  615.       case P_ENUMLIT:
  616.     assert(FALSE);
  617.     break;
  618.       case P_CONSTDECL:
  619.       case P_VARDECL:
  620.       case P_VECTORLIT:
  621.       case P_PRAGMA:
  622.       case P_MONITOR:
  623.       case P_OPDEF:
  624.       case P_PROCESSDEF:
  625.       case P_INITDEF:
  626.       case P_RECOVERYDEF:
  627.       case P_BLOCK:
  628.       case P_UNAVAILABLEHANDLER:
  629.       case P_FAILUREHANDLER:
  630.       case P_IFSTAT:
  631.       case P_IFCLAUSE:
  632.       case P_ELSECLAUSE:
  633.       case P_LOOPSTAT:
  634.       case P_EXITSTAT:
  635.       case P_ASSIGNSTAT:
  636.       case P_ASSERTSTAT:
  637.       case P_FIXSTAT:
  638.       case P_REFIXSTAT:
  639.       case P_UNFIXSTAT:
  640.       case P_MOVESTAT:
  641.       case P_VIEW:
  642.       case P_EXP:
  643.       case P_INVOC:
  644.     break;
  645.       case P_FIELDSEL:
  646.       case P_NTHRESULT:
  647.       case P_KNOWCT:
  648.       case P_KNOWLOCAL:
  649.       case P_KNOWMANIFEST:
  650.       case P_SUBSCRIPT:
  651.       case P_SELECTION:
  652.     assert(FALSE);
  653.     break;
  654.       case P_WHEREWIDGIT:
  655.       case P_PRIMSTAT:
  656.       case P_WAITSTAT:
  657.       case P_SIGNALSTAT:
  658.       case P_UNARYEXP:
  659.       case P_RESTRICT:
  660.       case P_SETQ:
  661.     break;
  662.       default:
  663.     break;
  664.     }
  665.     if (!done) {
  666.       writeBody(fNode, fNode->firstChild);
  667.       for (i = fNode->firstChild; i < fNode->nChildren; i++) {
  668.     writeInt(getOffset(fNode->b.children[i]));
  669.       }
  670.       for (i = fNode->firstChild; i < fNode->nChildren; i++) {
  671.     Pass2(fNode->b.children[i], FALSE);
  672.       }
  673.     }
  674.   }
  675. }
  676.  
  677. void writeTree(fileName, p)
  678. char *fileName;
  679. NodePtr p;
  680. {
  681.   char *treeName;
  682.   NodePtr symdef;
  683.  
  684.   if (BODYSIZE != 8) assert(FALSE);
  685.   aGlobalRef = Construct(P_GLOBALREF, 0);
  686.   fp = fopen(fileName, "w");
  687.   theOIDFileName = fileName;
  688.   assert (fp != NULL);
  689.   p = GETVALUE(p);
  690.   symdef = p->tag == P_OBLIT ? p->b.oblit.name : p->b.atlit.name;
  691.   if (symdef == NULL) treeName = "unknown";
  692.   else treeName = ST_Fetch(symdef->b.symdef.symbol)->itsName;
  693.   if (!bflag || (p->b.oblit.id & 0xffffff) > (OID)0x000100) {
  694.     treeName = malloc(20);
  695.     sprintf(treeName, "OID%08x", p->b.oblit.id);
  696.   }
  697.   initializeOutput(treeName);
  698.   theRoot = p;
  699.   doneFirstNode = FALSE;
  700.   Pass1(p, FALSE);
  701.   Pass1CTs();
  702.   intermediate();
  703.   doneFirstNode = FALSE;
  704.   Pass2(p, FALSE);                /* writes the data */
  705.   Pass2CTs();
  706.   finalize();                /* relocation and symtab */
  707.   if (fclose(fp) == EOF) assert(FALSE);
  708.   fp = NULL;
  709. }
  710.